/*
*
==============================================================================
*  Name        : 
*  Part of     : Omen Game Engine
*  Description : 
*  Version     : 1.0
*
*  Copyright (c) 2013 Lauri Kortevaara.
* 
==============================================================================
*/

#define OMEN_SOURCE 1

#include <OmenMath.h>
#include <OmenVector3d.h>

#include <iostream>
#include <iomanip>
#include <sstream>

using namespace Omen;

///
/// <summary>Default constructor of Matrix3x3 returns a identity matrix</summary>
///
Matrix3x3::Matrix3x3()
{
    memset(&m, 0, 9*sizeof(Omen::Float) );
    m[0] = m[3] = m[8] = static_cast<Omen::Float>(1.0);
}

///
/// <summary></summary>
///
Matrix3x3::Matrix3x3( const Omen::Float& m11, const Omen::Float& m12, const Omen::Float& m13,
                      const Omen::Float& m21, const Omen::Float& m22, const Omen::Float& m23,
                      const Omen::Float& m31, const Omen::Float& m32, const Omen::Float& m33)
{
    m[0] = m11;m[1] = m12;m[2] = m13;
    m[3] = m21;m[4] = m22;m[5] = m23;
    m[6] = m31;m[7] = m32;m[8] = m33;
}

///
/// <summary></summary>
///
Matrix3x3::Matrix3x3( const Matrix3x3& other )
{
    memcpy(&m, other.m, 9*sizeof(Omen::Float) );
}


///
/// <summary></summary>
///
Matrix3x3::~Matrix3x3()
{
    memset(&m, 0, 9*sizeof(Omen::Float) );
}
        

///
/// <summary></summary>
///
bool Matrix3x3::isIdentity() const
{
    bool bIsIdentity = true;
    for(unsigned char i=0; i<3; i++)
    {
        for(unsigned char j=0; j<3; j++)
        {
            if(m[i*3+j] != 1&& m[j*3+i] !=0)
            {
                bIsIdentity = false;
                break;
            }
        }
    }
    return bIsIdentity;
}

///
/// <summary></summary>
///
void Matrix3x3::setToIdentity ()
{
    memset(&m, 0, 9*sizeof(Omen::Float) );
    m[0] = m[3] = m[8] = static_cast<Omen::Float>(1.0);
}

///
/// <summary>Returns a transpose of this vector</summary>
///
Matrix3x3 Matrix3x3::transposed () const
{
    Matrix3x3 copy(*this);
    for( unsigned char i = 0; i < 3; ++i )
        for( unsigned char j = 0; j < 3; ++j )
            copy.m[i*3+j] = m[i*3+j];
    
    return copy;
}

Matrix3x3&  Matrix3x3::inverted( bool* isInvertible )
{
    Omen::Float det = determinant();
    if( det == 0.0 )
    {
        *isInvertible = false;
        return *this;
    }

    det = static_cast<Omen::Float>(1.0)/det;
    *this *= det;
    
    return *this;
}
        
///
/// <summary>Returns true if this matrix is not the other when all elements are compared</summary>
///
bool Matrix3x3::operator!= ( const Matrix3x3& other ) const
{
    bool bFlag = false;
    for( unsigned char i = 0; i < 9; ++i )
        if(m[i] != other.m[i] )
        {
            bFlag = true;
            break;
        }
    return bFlag;
}

///
/// <summary>Returns the determinant of this 3x3 square matrix</summary
///
/// [0][1][2]
/// [3][4][5]
/// [6][7][8]
///
/// det = m0*m4*m8 + m1*m5*m6 + m2*m3*m7 - m2*m4*m6 - m1*m3*m8 - m0*m5*m7
///
Omen::Float Matrix3x3::determinant() const
{
    return m[0]*m[4]*m[8] + m[1]*m[5]*m[6] + m[2]*m[3]*m[7] - m[2]*m[4]*m[6] - m[1]*m[3]*m[8] - m[0]*m[5]*m[7];
}

///
/// <summary></summary>
///
const Omen::Float& Matrix3x3::operator() ( int row, int column ) const
{
    if( row < 3&& column < 3 )
        return m[row*3+column];
    else
        return m[0];
}
        
///
/// <summary></summary>
///
Omen::Float& Matrix3x3::operator() ( int row, int column )
{
    if( row < 3&& column < 3 )
        return m[row*3+column];
    else
        return m[0];
}

///
/// <summary></summary>
///
Matrix3x3& Matrix3x3::operator*= ( Omen::Float scalar )
{
    for( unsigned char i = 0; i < 9; ++i )
        m[i] *= scalar;
    
    return *this;
}

///
/// <summary></summary>
///
Matrix3x3& Matrix3x3::operator+= ( const Matrix3x3& other )
{
    for( unsigned char i = 0; i < 9; ++i )
        m[i] += other.m[i];
    
    return *this;
}

///
/// <summary></summary>
///
Matrix3x3& Matrix3x3::operator-= ( const Matrix3x3& other )
{
    for( unsigned char i = 0; i < 9; ++i )
        m[i] -= other.m[i];
    
    return *this;
}

///
/// <summary></summary>
///
Matrix3x3& Matrix3x3::operator/= ( Omen::Float scalar )
{
    for( unsigned char i = 0; i < 9; ++i )
        m[i] /= scalar;
    
    return *this;
}

///
/// <summary></summary>
///
bool Matrix3x3::operator==( const Matrix3x3& other ) const
{
    bool bFlag = true;
    for( unsigned char i = 0; i < 9; ++i )
        if(m[i] != other.m[i] )
        {
            bFlag = false;
            break;
        }
    return bFlag;
}
/// EOF
